package org.flashbrighton.as3bots.logic
{
	import org.flashbrighton.as3bots.models.CollidableType;
	import org.flashbrighton.as3bots.events.BotEvent;

	public class OlliesBotLogic implements IBotLogic
	{
		private var engineVal:Number = 1;
		private var rotateVal:Number = 0;
		
		
		// routines
		private var frame:Number = 0;
		private var routineStop:Number = -1;
		private var routineFrame:Number = 0;
		private var routineType:Number = 0;

		public static const DEFAULT:Number = 0;
		public static const AVOID_WALL:Number = 1;
		public static const AVOID_BOT:Number = 2;
		public static const OPTIMIZE_BOT_HIT:Number = 3;
		
		// optimize routines
		private var lastPoints:Number = 9999;
		private var secondLastPoints:Number = 9999;
		private var optimizeRotateDirection:Number = 1;

		public function notify(event:BotEvent):void
		{	
			// record last bot hit points
			switch(event.targetType) {
				case CollidableType.BOT:
					trace("NOTIFY\t\tbot hit, recording values");
					secondLastPoints = lastPoints;
					lastPoints = event.points;
					break;
			}	
			
			// ignore events if we're in a special routine
			if(frame < routineStop) {
				trace("\tin a routine, ignoring event");
				return;
			}
			
			// avoid bot if hit in the back
			if((event.collisionPoint < -0.5) || (event.collisionPoint > 0.5)) {
				trace("NOTIFY\t\tback hit - avoiding bot");
				routineType = AVOID_BOT;
				startRoutine(10);
				return;
			}
			
			// front hits trigger optimize or wall avoid
			switch(event.targetType) {
				case CollidableType.BOT:
					// optimize angle
					trace("NOTIFY\t\tfront hit bot, entering optimize routine");
					lastPoints = event.points;
					routineType = OPTIMIZE_BOT_HIT;
					startRoutine(60);
					break;
				
				case CollidableType.WALL:
					// avoid
					trace("NOTIFY\t\tfront hit wall");
					routineType = AVOID_WALL;
					startRoutine(10);
					break;
			}				
		}
		
		private function startRoutine(length:Number):void {
			routineStop = frame + length;
			routineFrame = 0;
			trace("starting routine *****");
		}
				
		public function run():void
		{
			frame++;
			routineFrame++;
			
			if(frame > routineStop) {
				trace("ending routine *****");
				routineType = DEFAULT;
			}
			
			switch(routineType) {
				case DEFAULT:
					engineVal = 1;
					rotateVal = 0;
					break;

				case AVOID_BOT:
				case AVOID_WALL:
					avoidWallRoutine();
					break;

				case OPTIMIZE_BOT_HIT:
					optimizeRoutine();
					break;
			}
		}
		
		// =====================
		// routines
		// ======================
		private function avoidWallRoutine():void {
			if(routineFrame < 8) {
				trace("\tAVOID reverse");
				rotateVal = 0;
				engineVal = -1;
			} else if(routineFrame < 10) {
				trace("\tAVOID turn");
				rotateVal = 1;
				engineVal = -0.2;
			}
		}

		private function optimizeRoutine():void {
			if(routineFrame == 1) {
				trace("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
				rotateVal = 0;
			}
			
			var diff:Number = lastPoints - secondLastPoints;
			
			// if we got less points, ie better angle, continue
			if(lastPoints < secondLastPoints) {
				trace("\tOPTIMIZE routine, diff="+diff+", moving toward");
				optimizeRotateDirection = -1;
				
			} else {
				trace("\tOPTIMIZE routine, diff="+diff+", moving away");
				optimizeRotateDirection = 1;
			}
			
			engineVal = 1;
			rotateVal = rotateVal + (optimizeRotateDirection * 0.02);
		}
		
		
		public function get rotatorPercent():Number
		{
			return rotateVal;
		}
		
		public function get enginePercent():Number
		{
			return engineVal;
		}
		
	}
}